﻿using RakutenProxy.Model.NopCommerce;
using RakutenProxy.Model.Rakuten;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;

namespace RakutenProxy.DataConverter
{
    public class RakNopProductAttributeConverter : RakNopDataConverter<RakutenProxy.Model.Rakuten.ProductAttribute, RakutenProxy.Model.NopCommerce.ProductAttribute>
    {
        public RakNopProductAttributeConverter(DbContext sourceDbContext, DbContext targetDbContext)
            : base(sourceDbContext, targetDbContext)
        {
        }

        protected override Model.NopCommerce.ProductAttribute GetObjectFromSource(Model.Rakuten.ProductAttribute source)
        {
            var nopProductAttribute = new RakutenProxy.Model.NopCommerce.ProductAttribute();

            nopProductAttribute.Name = Translate(source.Name);

            return nopProductAttribute;
        }

        protected override void UpdateObjectFromSource(Model.NopCommerce.ProductAttribute target, Model.Rakuten.ProductAttribute source)
        {
            target.Name = source.Name;
        }

        public override void Migrate()
        {
            var rakDbContext = (RakutenDbContext)SourceContext;
            var nopDbContext = (NopCommerceEntities)TargetContext;

            var mappedAttributeIds = rakDbContext.Rakuten_NopCommerce_ProductAttribute_Maps.Select(m => m.RakutenProductAttributeId);
            var notMappedAttributes = rakDbContext.ProductAttributes.Where(a => !mappedAttributeIds.Contains(a.ProductAttributeId));
            var mappedAttributes = rakDbContext.ProductAttributes.Except(notMappedAttributes);

            foreach (var attribute in notMappedAttributes)
            {
                var nopAttribute = GetObjectFromSource(attribute);
                nopDbContext.ProductAttributes.Add(nopAttribute);
                nopDbContext.SaveChanges();

                var map = new Rakuten_NopCommerce_ProductAttribute_Map { RakutenProductAttributeId = attribute.ProductAttributeId, NopCommerceProductAttributeId = nopAttribute.Id };
                rakDbContext.Rakuten_NopCommerce_ProductAttribute_Maps.Add(map);
            }

            foreach (var attribute in mappedAttributes)
            {
                var mapId = rakDbContext.Rakuten_NopCommerce_ProductAttribute_Maps.FirstOrDefault(m => m.RakutenProductAttributeId == attribute.ProductAttributeId);
                if (mapId != null)
                {
                    var nopAttribute = nopDbContext.ProductAttributes.FirstOrDefault(a => a.Id == mapId.NopCommerceProductAttributeId);
                    if (nopAttribute != null && !attribute.Equals(nopAttribute))
                    {
                        UpdateObjectFromSource(nopAttribute, attribute);
                    }
                }
            }

            nopDbContext.SaveChanges();
            rakDbContext.SaveChanges();
        }

        public override void MigrateOneRecord(int id)
        {
            var rakDbContext = (RakutenDbContext)SourceContext;
            var nopDbContext = (NopCommerceEntities)TargetContext;

            var rakProductAttribute = rakDbContext.ProductAttributes.FirstOrDefault(p => p.ProductAttributeId == id);
            if (rakProductAttribute == null)
                return;

            var map = rakDbContext.Rakuten_NopCommerce_ProductAttribute_Maps.FirstOrDefault(m => m.RakutenProductAttributeId == id);
            if (map == null)
            {
                var nopAttribute = GetObjectFromSource(rakProductAttribute);
                nopDbContext.ProductAttributes.Add(nopAttribute);
                nopDbContext.SaveChanges();

                map = new Rakuten_NopCommerce_ProductAttribute_Map { RakutenProductAttributeId = rakProductAttribute.ProductAttributeId, NopCommerceProductAttributeId = nopAttribute.Id };
                rakDbContext.Rakuten_NopCommerce_ProductAttribute_Maps.Add(map);
                rakDbContext.SaveChanges();
            }
            else
            {
                var nopProductAttribute = nopDbContext.ProductAttributes.FirstOrDefault(p => p.Id == map.NopCommerceProductAttributeId);
                if (nopProductAttribute != null)
                {
                    UpdateObjectFromSource(nopProductAttribute, rakProductAttribute);
                    nopDbContext.SaveChanges();
                }
            }
        }

        public override void RemoveOneRecord(int id)
        {
            var rakDbContext = (RakutenDbContext)SourceContext;
            var nopDbContext = (NopCommerceEntities)TargetContext;
                        
            var map = rakDbContext.Rakuten_NopCommerce_ProductAttribute_Maps.FirstOrDefault(m => m.RakutenProductAttributeId == id);
            if (map == null)
                return;

            var nopAttribute = nopDbContext.ProductAttributes.FirstOrDefault(a => a.Id == map.NopCommerceProductAttributeId);
            if (nopAttribute != null)
            {
                nopDbContext.ProductAttributes.Remove(nopAttribute);
            }

            rakDbContext.Rakuten_NopCommerce_ProductAttribute_Maps.Remove(map);

            rakDbContext.SaveChanges();
            nopDbContext.SaveChanges();
        }
    }
}